#ifndef _MOE_BLXCROSSOVER
#define _MOE_BLXCROSSOVER

#include <iostream>

#include "engine/Random.hh"
#include "problems/RealArraySolution.hh"
#include "engine/Crossover.hh"


/**It's an Crossover operator created for apply to a RealArraySolution instance
*/
class BLXCrossover: public Crossover {
private:
    double alpha;


public:

    BLXCrossover(double alpha = 0.5) : Crossover() {
        this->alpha = alpha;
    }

    virtual ~BLXCrossover() {}

    int matesExpected() {
        return 2;
    }

    void setAlpha(double alpha) {
        this->alpha = alpha;
    }

    double getAlpha() {
        return alpha;
    }

    ArrayList<Solution> *cross(ArrayList<Solution> *mates){
        RealArraySolution *mate1 = (RealArraySolution *)mates->get(0);
        RealArraySolution *mate2 = (RealArraySolution *)mates->get(1);

        RealArraySolution *child0 = new RealArraySolution();
        RealArraySolution *child1 = new RealArraySolution();

        for (int i = 0; i < RealArraySolution::getSize(); i++) {

            child0->set(i, combines(mate1->get(i), mate2->get(i)));
            child1->set(i, combines(mate1->get(i), mate2->get(i)));
        }

        ArrayList<Solution> *childs = new ArrayList<Solution>(false);
        childs->add(child0);
        childs->add(child1);

        return childs;
    }

private:

    double combines(double value1, double value2) {

        if (value1 > value2) {
            double temp = value1;
            value1 = value2;
            value2 = temp;
        }

        return Random::getInstance()->getReal(value1 - alpha*(value2 - value1), value2 + alpha*(value2 - value1));
    }
};


#endif
